{:
   @created(24 de abril de 2005)
   @lastmod(October 07th of 2007)
   @abstract(Main unit of the RSS 2.0 news generator. This software was used by
             Delphi Users Group Rio Grande do Sul, to generate news for its
             website.)
   @author(Daniel Wildt <dwildt@dug-rs.org>, DUG-RS leader,
           http://www.dug-rs.org)
   @html(
         With this software it is possible to maintain news in the RSS 2.0
         format. You can put this in your website to keep your visitors updated.
         <br><br>
         RSS means lots of things. Can be Really Simple Syndication, Rich Site
         Summary or RDF Site Summary. Those are some of the meanings you can get
         for RSS.
         <br><br>
         Bottom line, the RSS file is a XML file, which works with a standard
         notation. Check references bellow so you can learn more about this
         standard.
         <br><br>
         This software is a Creative Commons software. Check more informations
         about the license here:
         http://creativecommons.org/licenses/by-sa/3.0/.

         <hr>

          <br> Related information:
          <ul>
            <li> http://www.xml.com/pub/a/2001/01/24/rdf.html
                 "What is RDF?".
                 </li>
            <li> http://www.w3.org/RDF/
                 W3C standardadization about RDF.
                 </li>
            <li> http://www.faganfinder.com/search/rss.shtml
                 "All About RSS".
                 </li>
            <li> http://www.xml.com/pub/a/2002/12/18/dive-into-xml.html?page=1
                 "What is RSS?"
                 </li>
            <li> http://www.feedreader.com/
                 FeedReader, a rss reader built using Delphi. Source code
                 available for download.
                 </li>
            <li> http://thinfeeder.sourceforge.net/
                 ThinFeeder, a rss reader built using Java, by Fabiano Franz
                 (http://www.fabianofranz.com).
                 </li>
          </ul>
        )

}
unit UFormMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, xmldom, StdCtrls, Grids, DBGrids, DB, DBClient, Provider,
  Xmlxform, Buttons, Mask, DBCtrls, ComCtrls, ActnList, DBActns,
  DBClientActns, ExtCtrls, jpeg;

type
  {:
    @lastmod(October 07th of 2007)
    @abstract(Main class)
    @author(Daniel Wildt <dwildt@dug-rs.org>, from http://www.dug-rs.org)
  }
  TFrmMain = class(TForm)
    dsCDSRSS20: TDataSource;
    {: Responsible for the XML transformations. We have a transform read and
       write. }
    XMLTransformProvider: TXMLTransformProvider;
    {: Main dataset.}
    CDSRSS20: TClientDataSet;
    BtnGenerateRSS: TButton;
    CDSRSS20version: TStringField;
    CDSRSS20title: TStringField;
    CDSRSS20link: TStringField;
    CDSRSS20description: TStringField;
    CDSRSS20lastBuildDate: TStringField;
    CDSRSS20item: TDataSetField;
    PageControlRSSGenerator: TPageControl;
    tsChannelInformation: TTabSheet;
    tsNews: TTabSheet;
    CDSRSS20News: TClientDataSet;
    CDSRSS20Newstitle: TStringField;
    CDSRSS20Newsdescription: TStringField;
    CDSRSS20Newslink: TStringField;
    CDSRSS20Newsguid: TStringField;
    CDSRSS20Newscategory: TStringField;
    CDSRSS20NewspubDate: TStringField;
    lbVersion: TLabel;
    EdChannelVersion: TDBEdit;
    lbChannelTitle: TLabel;
    EdChannelTitle: TDBEdit;
    lbBaseLink: TLabel;
    EdChannelLink: TDBEdit;
    lbChannelDescription: TLabel;
    lbChannelLastModification: TLabel;
    EdLastBuildUpdateCanal: TDBEdit;
    BtnUpdateChannelLastBuildUpdate: TBitBtn;
    ActionList: TActionList;
    {: Action to execute Apply Updates. }
    ClientDataSetApplyAction: TClientDataSetApply;
    GridNoticias: TDBGrid;
    MemoChannelDescription: TDBMemo;
    EnableChannelLastBuildAction: TAction;
    DBNavigatorCanal: TDBNavigator;
    dsCDSRSS20News: TDataSource;
    DBNavigator1: TDBNavigator;
    lbTituloNoticia: TLabel;
    EdNewsTitle: TDBEdit;
    lbLinkNoticia: TLabel;
    EdNewsLink: TDBEdit;
    lbCategory: TLabel;
    ComboNewsCategory: TDBComboBox;
    EdNewsPubDate: TDBEdit;
    lbPublicadoEm: TLabel;
    BtnPubDate: TBitBtn;
    EnableNewsPubDateAction: TAction;
    lbNewsDescription: TLabel;
    MemoNewsDescription: TDBMemo;
    tsLicense: TTabSheet;
    MemoLicenca: TMemo;
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure CDSRSS20NewRecord(DataSet: TDataSet);
    procedure CDSRSS20BeforeInsert(DataSet: TDataSet);
    procedure CDSRSS20BeforeDelete(DataSet: TDataSet);
    procedure EnableChannelLastBuildActionUpdate(Sender: TObject);
    procedure EnableChannelLastBuildActionExecute(Sender: TObject);
    procedure CDSRSS20NewsBeforePost(DataSet: TDataSet);
    procedure EnableNewsPubDateActionUpdate(Sender: TObject);
    procedure EnableNewsPubDateActionExecute(Sender: TObject);
    procedure CDSRSS20ReconcileError(DataSet: TCustomClientDataSet;
      E: EReconcileError; UpdateKind: TUpdateKind;
      var Action: TReconcileAction);
    procedure CDSRSS20NewsAfterInsert(DataSet: TDataSet);
  end;

var
  FrmMain: TFrmMain;

implementation

uses Math;

{$R *.dfm}

procedure TFrmMain.FormCreate(Sender: TObject);
var
  CaminhoBase: string;
begin
  PageControlRSSGenerator.ActivePage := tsChannelInformation;

  // We are doing all the processing mapping the RSS file into a ClientDataSet.
  // This is all done by the XML transformations. We built that using the
  // XML Mapper.
  CaminhoBase := ExtractFilePath(Application.ExeName);

  // XML File
  XMLTransformProvider.XMLDataFile := CaminhoBase + 'rss20_news.xml';

  // Transformation files
  XMLTransformProvider.TransformRead.TransformationFile :=
    CaminhoBase + 'RSSToCDS.xtr';
  XMLTransformProvider.TransformWrite.TransformationFile :=
    CaminhoBase + 'CDSToRSS.xtr';

  // Categories file
  ComboNewsCategory.Items.LoadFromFile(
    CaminhoBase + 'categories.txt');
end;

procedure TFrmMain.FormShow(Sender: TObject);
begin
  CDSRSS20.Open;
end;

procedure TFrmMain.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  if (CDSRSS20.ChangeCount > 0) and
    (MessageDlg('News were modified! Save changes?', mtConfirmation,
    [mbYes, mbNo], 0) = mrYes) then
    CDSRSS20.ApplyUpdates(-1);
  CDSRSS20.Close;
end;

procedure TFrmMain.CDSRSS20NewRecord(DataSet: TDataSet);
begin
  DataSet.FieldByName('version').asString := '2.0';
end;

procedure TFrmMain.CDSRSS20BeforeInsert(DataSet: TDataSet);
begin
  if (DataSet.RecordCount = 1) then
    Exception.Create('It is not possible to include more than one channel!');
end;

procedure TFrmMain.CDSRSS20BeforeDelete(DataSet: TDataSet);
begin
  if (DataSet.RecordCount = 1) then
    Exception.Create('It is not possible to remove the channel');
end;

procedure TFrmMain.EnableChannelLastBuildActionUpdate(Sender: TObject);
begin
  EnableChannelLastBuildAction.Enabled := (CDSRSS20.State in [dsEdit,
    dsInsert]);
end;

procedure TFrmMain.EnableChannelLastBuildActionExecute(
  Sender: TObject);
begin
  dsCDSRSS20.DataSet.FieldByName('lastBuildDate').asString :=
    FormatDateTime('dd/mm/yyyy hh:ss:ss:zzz', now);
end;

procedure TFrmMain.CDSRSS20NewsBeforePost(DataSet: TDataSet);
begin
  DataSet.FieldByName('guid').asString :=
    DataSet.FieldByName('link').asString;
end;

procedure TFrmMain.EnableNewsPubDateActionUpdate(
  Sender: TObject);
begin
  EnableNewsPubDateAction.Enabled := (dsCDSRSS20News.DataSet.State in [dsEdit, dsInsert]);
end;

procedure TFrmMain.EnableNewsPubDateActionExecute(
  Sender: TObject);
begin
  dsCDSRSS20News.DataSet.FieldByName('pubDate').asString :=
    FormatDateTime('dd/mm/yyyy hh:ss:ss:zzz', now);
end;

procedure TFrmMain.CDSRSS20ReconcileError(
  DataSet: TCustomClientDataSet; E: EReconcileError;
  UpdateKind: TUpdateKind; var Action: TReconcileAction);
begin
  ShowMessage(E.Message);
  Action := raAbort;
end;

procedure TFrmMain.CDSRSS20NewsAfterInsert(DataSet: TDataSet);
begin
  PageControlRSSGenerator.ActivePage := tsNews;
  EdNewsTitle.SetFocus;
end;

end.

